package com.xjrsoft.module.form.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xjrsoft.common.result.Response;
import com.xjrsoft.common.utils.ChineseYuanUtil;
import com.xjrsoft.core.tool.utils.*;
import com.xjrsoft.module.base.constants.ModuleConstants;
import com.xjrsoft.module.base.entity.*;
import com.xjrsoft.module.base.service.IXjrBaseAnnexesFileService;
import com.xjrsoft.module.base.service.IXjrBaseAreaService;
import com.xjrsoft.module.base.service.IXjrBaseDataItemService;
import com.xjrsoft.module.base.service.IXjrBaseDatasourceService;
import com.xjrsoft.module.base.utils.OrganizationCacheUtil;
import com.xjrsoft.module.base.vo.DataItemDetailVo;
import com.xjrsoft.module.form.constant.FormConstants;
import com.xjrsoft.module.form.dto.ModuleFormDto;
import com.xjrsoft.module.form.dto.TableFieldDto;
import com.xjrsoft.module.form.dto.TableInfoDto;
import com.xjrsoft.module.interfaceManager.dto.AddInfoDto;
import com.xjrsoft.module.interfaceManager.dto.AddOutputDto;
import com.xjrsoft.module.interfaceManager.dto.AddParamDto;
import com.xjrsoft.module.interfaceManager.service.IXjrInterfaceInfoService;
import lombok.extern.slf4j.Slf4j;
import oracle.sql.CLOB;
import oracle.sql.NCLOB;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.tomcat.util.collections.CaseInsensitiveKeyMap;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Slf4j
public class FormDataUtil {

    private static final IXjrBaseDataItemService dataItemService;

    private static final IXjrBaseDatasourceService datasourceService;

    private static final IXjrBaseAreaService areaService;

    private static final IXjrBaseAnnexesFileService annexesFileService;

    private static final IXjrInterfaceInfoService interfaceInfoService;

    static {
        dataItemService = SpringUtil.getBean(IXjrBaseDataItemService.class);
        datasourceService = SpringUtil.getBean(IXjrBaseDatasourceService.class);
        annexesFileService = SpringUtil.getBean(IXjrBaseAnnexesFileService.class);
        areaService = SpringUtil.getBean(IXjrBaseAreaService.class);
        interfaceInfoService = SpringUtil.getBean(IXjrInterfaceInfoService.class);
    }

    private FormDataUtil(){}

    public static void transFormListData(JSONArray formFields, List<Map<String, Object>> records) {
        // 数据准备
        Map<String, List<Object>> fieldValueListMap = new CaseInsensitiveKeyMap<>();
        for (Map<String, Object> record : records) {
            for (Map.Entry<String, Object> entry: record.entrySet()) {
                Object value = entry.getValue();
                if (StringUtil.isEmpty(value)) {
                    continue;
                }
                if (value instanceof NCLOB) {
                    try {
                        value = ((NCLOB) value).stringValue();
                    } catch (SQLException e) {
                        log.error("NCLOB类型数据序列化失败！", e);
                    }
                }
                String key = entry.getKey();
                List<Object> values = fieldValueListMap.get(key);
                if (values == null) {
                    values = new ArrayList<>();
                    fieldValueListMap.put(key, values);
                }
                values.add(value);
            }
        }
        Map<String, Map<String, Object>> dataMap = new HashMap<>(16);
        Map<String, String> multiValueSeparatorMap = new HashMap<>();
        for (Object fieldObj : formFields) {
            JSONObject field = (JSONObject) fieldObj;
            JSONObject config = field.getJSONObject(FormConstants.CONFIG);
            String componentName = MapUtils.getString(config, FormConstants.FORM_COMPONENT_NAME);
            if (StringUtil.equalsIgnoreCase(componentName, "avue-tabs")) {
                JSONObject tabsJson = config.getJSONObject("childrenObj");
                for (Object tabObj : tabsJson.values()) {
                    JSONArray tabComponents = (JSONArray) tabObj;
                    for (Object tabComponentObj : tabComponents) {
                        JSONObject tabComponent = (JSONObject) tabComponentObj;
                        JSONObject subConfig = tabComponent.getJSONObject(FormConstants.CONFIG);
                        String fieldName = MapUtils.getString(subConfig, FormConstants.BIND_TABLE_FIELD);
                        buildFieldData(dataMap, multiValueSeparatorMap, tabComponent, fieldValueListMap, fieldName);
                    }
                }
            } else {
                String fieldName = MapUtils.getString(config, FormConstants.BIND_TABLE_FIELD);
                buildFieldData(dataMap, multiValueSeparatorMap, field, fieldValueListMap, fieldName);
            }
        }
        for (Map<String, Object> record : records) {
            for (String fieldName : dataMap.keySet()) {
                Object value = record.get(fieldName);
                if (value instanceof CLOB) {
                    try {
                        value = ((NCLOB) value).stringValue();
                    } catch (SQLException e) {
                        log.error("NCLOB类型数据序列化失败！", e);
                    }
                } else {
                    value = StringUtil.isEmpty(record.get(fieldName)) ? null : String.valueOf(value);
                }
                Map<String, Object> data = dataMap.get(fieldName);
                if (data == null || StringUtil.isEmpty(value)) {
                    continue;
                }
                Object transToValue = null;
                if (multiValueSeparatorMap.keySet().contains(fieldName)) {
                    String[] values = StringUtils.split(String.valueOf(value), StringPool.COMMA);
                    StringBuilder sb = new StringBuilder();
                    for (int i = 0; i < values.length; i++) {
                        Object obj = data.get(values[i]);
                        if (obj != null) {
                            if (i != 0) {
                                sb.append(multiValueSeparatorMap.get(fieldName));
                            }
                            sb.append(obj);
                        }
                    }
                    transToValue = sb.toString();
                } else {
                    transToValue = data.get(value);
                }
                if (!(transToValue == null || "".equals(transToValue))) {
                    record.put(fieldName, transToValue);
                }
            }
        }
    }

    public static void buildFieldData(Map<String, Map<String, Object>> dataMap, Map<String, String> multiValueSeparatorMap,
                                       JSONObject field, Map<String, List<Object>> fieldValueListMap,String fieldName) {
        JSONObject config = field.getJSONObject(FormConstants.CONFIG);
//        String fieldName = MapUtils.getString(config, FormConstants.BIND_TABLE_FIELD);
        List<Object> values = fieldValueListMap.get(fieldName);
        if (CollectionUtil.isEmpty(values)) {
            return;
        }
        String avueType = MapUtils.getString(config, "avueType");
        String componentType = MapUtils.getString(field, FormConstants.FIELD_TYPE);
        String dataType = getDataType(field);
        boolean isMulti = false;
        String separator = StringPool.COMMA;
        Map<String, Object> data = new HashMap<>(16);
        switch (StringUtils.lowerCase(dataType)) {
            case "dataitem":
                // 数据字典
                String itemCode = MapUtils.getString(config, "dataItem");
                List<DataItemDetailVo> dataItemDetails = dataItemService.getDataItemDetails(itemCode);
                for (DataItemDetailVo detail : dataItemDetails) {
                    data.put(detail.getItemValue(), detail.getItemName());
                }
                break;
            case "datasource":
                // 数据源
                String datasourceId = MapUtils.getString(config, "dataSource");
                String showField = MapUtils.getString(config, "showField");
                String saveField = MapUtils.getString(config, "saveField");
                String columns = showField + StringPool.COMMA + saveField;
                try {
                    List<Map<String, Object>> datasourceDataList = datasourceService.getDataByColumns(datasourceId, columns);
                    for (Map<String, Object> resultData : datasourceDataList) {
                        data.put(String.valueOf(resultData.get(saveField)), resultData.get(showField));
                    }
                } catch (Exception e) {
                    log.error("查询数据源失败！id: " + datasourceId, e);
                }
                break;
            case "datasql":
                // 数据源
                String dbId = MapUtils.getString(config, "database");
                String sqlShowField = MapUtils.getString(config, "showField");
                String sqlSaveField = MapUtils.getString(config, "saveField");
                String sql = MapUtils.getString(config, "sql");
                String sqlColumns = sqlShowField + StringPool.COMMA + sqlSaveField;
                List<Map<String, Object>> datasourceDataList = datasourceService.getDataBySql(dbId, sql, sqlColumns);
                for (Map<String, Object> resultData : datasourceDataList) {
                    data.put(String.valueOf(resultData.get(sqlSaveField)), resultData.get(sqlShowField));
                }
                break;
            case "dataapi" :
                Map<String, Object> apiConfig = MapUtils.getMap(config, "apiConfig");
                String id = MapUtils.getString(apiConfig, "id");
                String apiShowField = MapUtils.getString(apiConfig, "showField");
                String apiSaveField = MapUtils.getString(apiConfig, "saveField");
                String prefix = MapUtils.getString(apiConfig, "dataSource");
                Object resultData = null;
                try {
                    Response response = interfaceInfoService.execute(id, new HashMap<>(), WebUtil.getRequest());
                    resultData = (Map) response.getData();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
                if (resultData == null) {
                    break;
                }
                List<Map<String, Object>> jsonArray = (List<Map<String, Object>>)(StringUtil.isEmpty(prefix) ? resultData : ((Map<String, Object>)resultData).get(prefix));
                if(CollectionUtil.isNotEmpty(jsonArray)) {
                    for (Map<String, Object> item : jsonArray) {
                        data.put(MapUtils.getString(item, apiSaveField), MapUtils.getString(item, apiShowField));
                    }
                }
                break;
            case "company":
                // 公司
                List<XjrBaseCompany> companyList = OrganizationCacheUtil.getCacheListByIds(OrganizationCacheUtil.COMPANY_LIST_CACHE_KEY, values);
                for (XjrBaseCompany company : companyList) {
                    data.put(company.getCompanyId(), company.getFullName());
                }
                break;
            case "department":
                // 部门
                List<XjrBaseDepartment> allDepartmentList = OrganizationCacheUtil.getCacheListByIds(OrganizationCacheUtil.DEPARTMENT_LIST_CACHE_KEY, values);
                for (XjrBaseDepartment department : allDepartmentList) {
                    data.put(department.getDepartmentId(), department.getFullName());
                }
                break;
            case "user":
                // 人员
                Set<Object> userIds = new LinkedHashSet<>();
                if (CollectionUtil.isNotEmpty(values)) {
                    for (Object obj : values) {
                        userIds.addAll(StringUtil.split(String.valueOf(obj), ',', -1));
                    }
                }
                List<XjrBaseUser> allUserList = OrganizationCacheUtil.getCacheListByIds(OrganizationCacheUtil.USER_LIST_CACHE_KEY, userIds);
                for (XjrBaseUser user : allUserList) {
                    data.put(user.getUserId(), user.getRealName());
                }
                break;
            case "area":
                Set<Object> areaIds = new LinkedHashSet<>();
                if (CollectionUtil.isNotEmpty(values)) {
                    for (Object obj : values) {
                        areaIds.addAll(StringUtil.split(String.valueOf(obj), ',', -1));
                    }
                }
                List<XjrBaseArea> areaList = areaService.list(Wrappers.<XjrBaseArea>query().lambda().in(XjrBaseArea::getAreaCode, areaIds));
                for (XjrBaseArea area : areaList) {
                    data.put(area.getAreaCode(), area.getAreaName());
                }
                break;
            case "cascade":
                List<Map<String, Object>> settings = (List<Map<String, Object>>) config.get("settings");
                isMulti = MapUtils.getBoolean(field, "show-all-levels");
                separator = MapUtils.getString(field, "separator");
                int start = MapUtils.getBoolean(field, "show-all-levels") ? 0 : settings.size() - 1;
                for (int i = start; i < settings.size(); i++) {
                    Map<String, Object> setting = settings.get(i);
                    String caseDbId = MapUtils.getString(setting, "dataSource");
                    String caseShowField = MapUtils.getString(setting, "showField");
                    String caseSaveField = MapUtils.getString(setting, "saveField");
                    List<Map<String, Object>> dataList = null;
                    try {
                        dataList = datasourceService.getDataByColumns(caseDbId, caseShowField + StringPool.COMMA + caseSaveField);
                    } catch (Exception e) {
                        log.error("数据转换，查询sql数据失败！", e);
                    }
                    if (CollectionUtil.isNotEmpty(dataList)) {
                        for (Map<String, Object> map : dataList) {
                            data.put(String.valueOf(map.get(caseSaveField)), map.get(caseShowField));
                        }
                    }
                }
                break;
            case "ch_yuan":
                for (Object obj : values) {
                    String amount = String.valueOf(obj);
                    data.put(amount, ChineseYuanUtil.convertToYuan(amount));
                }
                break;
            case "number":
                Integer precision = MapUtils.getInteger(field, "precision");
                if (CollectionUtil.isNotEmpty(values) && precision != null) {
                    for (Object obj : values) {
                        DecimalFormat instance = (DecimalFormat) NumberFormat.getInstance();
                        String pattern = "#0." + StringUtils.substring("000000000000000", 0, precision);
                        instance.applyPattern(pattern);
                        data.put(String.valueOf(obj), instance.format(Double.parseDouble(String.valueOf(obj))));
                    }
                }
                break;
            case "datetime":
                String pattern = null;
                if (StringUtil.equalsIgnoreCase(MapUtils.getString(field, "type"),"week")) {
                    pattern = "yyyy 第w周";
                } else {
                    pattern = MapUtils.getString(field, "format");
                }
                if (!StringUtil.isEmpty(pattern)) {
                    for (Object obj : values) {
                        LocalDateTime date = null;
                        if (obj instanceof java.sql.Timestamp) {
                            date = ((Timestamp)obj).toLocalDateTime();
                        } else if (obj instanceof LocalDateTime) {
                            date = (LocalDateTime) obj;
                        }
                        if (date != null) {
                            data.put(String.valueOf(obj), date.format(DateTimeFormatter.ofPattern(pattern)));
                        }
                    }
                }
                break;
            case "file":
                List<XjrBaseAnnexesFile> annexesFileList = annexesFileService.list(Wrappers.<XjrBaseAnnexesFile>query()
                        .lambda().in(XjrBaseAnnexesFile::getFolderId, values));
                if (CollectionUtil.isNotEmpty(annexesFileList)) {
                    for (XjrBaseAnnexesFile annexesFile : annexesFileList) {
                        String folderId = annexesFile.getFolderId();
                        String fileName = annexesFile.getFileName();
                        StringBuilder stringBuilder = (StringBuilder) data.get(folderId);
                        if (stringBuilder == null) {
                            stringBuilder = new StringBuilder(fileName);
                            data.put(folderId, stringBuilder);
                        } else {
                            stringBuilder.append(", " + fileName);
                        }
                    }
                }
                break;
        }
        if (StringUtil.equalsIgnoreCase(avueType, "checkbox") || StringUtil.equalsIgnoreCase(componentType, "user")
                || StringUtil.equalsIgnoreCase(avueType, "select-area") || StringUtil.equalsIgnoreCase(avueType, "mutiple-popup")) {
           isMulti = true;
        }
        if (isMulti) {
            // 多选字段
            multiValueSeparatorMap.put(fieldName, separator);
        }
        dataMap.put(fieldName, data);
    }

    private static String getDataType(JSONObject field) {
        JSONObject config = field.getJSONObject(FormConstants.CONFIG);
        String dataType = StringPool.EMPTY;
        String avueType = MapUtils.getString(config, "avueType");
        String componentType = MapUtils.getString(field, FormConstants.FIELD_TYPE);
        if (StringUtil.equals(avueType, "select") ||
                StringUtil.equals(avueType, "radio") ||
                StringUtil.equals(avueType, "checkbox") ||
                StringUtil.equals(avueType, "asso-select") ||
                StringUtil.equals(avueType, "mutiple-popup") ||
                StringUtil.equals(avueType, "asso-popup")) {
            dataType = MapUtils.getString(config, "dataType");
        } else if (StringUtil.equals(componentType, "info") ||
                StringUtil.equals(componentType, "company") ||
                StringUtil.equals(componentType, "department") ||
                StringUtil.equals(componentType, "user")) {
            String infoType = MapUtils.getString(field, FormConstants.FIELD_TYPE_OF_INFO_TYPE);
            dataType = StringUtil.equals(componentType, "info") ? infoType : componentType;
        } else if (StringUtil.equalsIgnoreCase(avueType, "select-area")) {
            dataType = "area";
        } else if (StringUtil.equalsIgnoreCase(avueType, "datetime")) {
            // 日期时间格式化
            dataType = "datetime";
        } else if (StringUtil.equalsIgnoreCase(avueType, "cascader")) {
            dataType = "cascade";
        } else if (MapUtils.getBoolean(field, "isCapitalized", false)) {
            dataType = "ch_yuan";
        } else if (StringUtil.equalsIgnoreCase(avueType, "upload")) {
            dataType = "file";
        } else {
            dataType = StringUtil.isEmpty(avueType) ? StringPool.EMPTY : avueType;
        }
        return dataType;
    }

    /**
     *
     * @param componentType
     * @return
     */
    public static String getQueryType(String componentType){
        String resultType = StringPool.EMPTY;
        if (StringUtil.equalsIgnoreCase(componentType, "input-tip")
                || StringUtil.equalsIgnoreCase(componentType, "textarea")
                || StringUtil.equalsIgnoreCase(componentType, "autoCode")
                || StringUtil.equalsIgnoreCase(componentType, "ueditor")
                || StringUtil.equalsIgnoreCase(componentType, "mutiple-popup")
                || StringUtil.equalsIgnoreCase(componentType, "checkbox")) {
            resultType = "like";
        } else {
            resultType = "equal";
        }
        return resultType;
    }

    /**
     * @param tableRelationList 表关联关系对象集合
     * @param tableInfoList 表配置信息对象集合
     */
    public static void buildRelationField(JSONArray tableRelationList, List<TableInfoDto> tableInfoList) {
        if (CollectionUtil.isNotEmpty(tableRelationList) && tableRelationList.size() > 1) {
            String mainTableName = StringPool.EMPTY;
            Map<String, String> tableRelationFiledNameMap = new HashMap<>(tableInfoList.size() - 1);
            for (Object tableRelationObj : tableRelationList) {
                JSONObject tableRelation = (JSONObject) tableRelationObj;
                if (!StringUtil.isEmpty(tableRelation.getString(FormConstants.DB_TABLE_RELATION_NAME))) {
                    tableRelationFiledNameMap.put(tableRelation.getString(FormConstants.DB_TABLE_NAME), tableRelation.getString(FormConstants.DB_TABLE_FIELD));
                } else {
                    mainTableName = tableRelation.getString(FormConstants.DB_TABLE_NAME);
                }
            }
            for (TableInfoDto tableInfo : tableInfoList) {
                String relationFieldName = tableRelationFiledNameMap.get(tableInfo.getName());
                if(!StringUtil.isEmpty(relationFieldName)) {
                    TableFieldDto relationField = new TableFieldDto();
                    relationField.setLength(50);
                    relationField.setComment(mainTableName + "主键值");
                    relationField.setType("varchar");
                    relationField.setName(relationFieldName);
                    tableInfo.getFields().add(relationField);
                }
            }
        }
    }

    public static List<AddInfoDto> buildInterfaceInfo(ModuleFormDto moduleFormDto, JSONArray dbTables, JSONArray colFields, boolean isImported) {
        List<AddInfoDto> resultList = new ArrayList<>();
        String baseUrl = "/{id}/instance-form-list";
        String categoryId = moduleFormDto.getCategoryId();
        // 新增
        AddInfoDto addInfo = new AddInfoDto();
        addInfo.setCategoryId(categoryId);
        addInfo.setIsCustomize(0);
        addInfo.setEnCode(moduleFormDto.getEnCode() + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "add");
        addInfo.setName(moduleFormDto.getFullName() + "新增接口");
        addInfo.setIsInternal(0);
        addInfo.setRequestMethod(1);
        addInfo.setUrlAddress(baseUrl);
        addInfo.setParams(new ArrayList<>());
        resultList.add(addInfo);
        // 删除
        AddInfoDto deleteInfo = new AddInfoDto();
        deleteInfo.setCategoryId(categoryId);
        deleteInfo.setIsCustomize(0);
        deleteInfo.setEnCode(moduleFormDto.getEnCode() + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "delete");
        deleteInfo.setName(moduleFormDto.getFullName() + "删除接口");
        deleteInfo.setIsInternal(0);
        deleteInfo.setRequestMethod(3);
        deleteInfo.setUrlAddress(baseUrl + "/{id}");
        resultList.add(deleteInfo);
        // 列表查询
        AddInfoDto queryInfo = new AddInfoDto();
        queryInfo.setCategoryId(categoryId);
        queryInfo.setIsCustomize(0);
        queryInfo.setEnCode(moduleFormDto.getEnCode() + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "list");
        queryInfo.setName(moduleFormDto.getFullName() + "列表查询接口");
        queryInfo.setIsInternal(0);
        queryInfo.setRequestMethod(0);
        queryInfo.setUrlAddress(baseUrl);
        queryInfo.setOutputs(new ArrayList<>());
        resultList.add(queryInfo);
        // 编辑查询
        AddInfoDto editInfo = new AddInfoDto();
        editInfo.setCategoryId(categoryId);
        editInfo.setIsCustomize(0);
        editInfo.setEnCode(moduleFormDto.getEnCode() + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "list");
        editInfo.setName(moduleFormDto.getFullName() + "ID查询接口");
        editInfo.setIsInternal(0);
        editInfo.setRequestMethod(0);
        editInfo.setUrlAddress(baseUrl + "/{id}");
        editInfo.setOutputs(new ArrayList<>());
        resultList.add(editInfo);
        // 修改
        AddInfoDto updateInfo = new AddInfoDto();
        updateInfo.setCategoryId(categoryId);
        updateInfo.setIsCustomize(0);
        updateInfo.setEnCode(moduleFormDto.getEnCode() + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "list");
        updateInfo.setName(moduleFormDto.getFullName() + "修改接口");
        updateInfo.setIsInternal(0);
        updateInfo.setRequestMethod(2);
        updateInfo.setUrlAddress(baseUrl + "/{id}");
        updateInfo.setParams(new ArrayList<>());
        resultList.add(updateInfo);
        // 导入
        if (isImported) {
            AddInfoDto importInfo = new AddInfoDto();
            importInfo.setCategoryId(categoryId);
            importInfo.setIsCustomize(0);
            importInfo.setEnCode(moduleFormDto.getEnCode() + com.baomidou.mybatisplus.core.toolkit.StringPool.UNDERSCORE + "list");
            importInfo.setName(moduleFormDto.getFullName() + "导入接口");
            importInfo.setIsInternal(0);
            importInfo.setRequestMethod(1);
            importInfo.setUrlAddress("/excel-import/import");
            resultList.add(importInfo);
        }
        for (Object obj : dbTables) {
            JSONObject table = (JSONObject) obj;
            AddParamDto updateParam = new AddParamDto();
            updateParam.setParamKey(table.getString("name"));
            updateParam.setIsCustom(0);
            updateParam.setType(1);
            updateInfo.getParams().add(updateParam);
            AddParamDto addParam = BeanUtil.copy(updateParam, AddParamDto.class);
            addInfo.getParams().add(addParam);
        }

        for (Object obj : colFields) {
            JSONObject column = (JSONObject) obj;
            String columnName = column.getString("bindColumn");
            AddOutputDto outputDto = new AddOutputDto();
            outputDto.setOutputKey(columnName);
            outputDto.setType(0);
            queryInfo.getOutputs().add(outputDto);
        }
        return resultList;
    }

    public static List<Map<String, Object>> getFullFieldList(List<Map<String, Object>> fieldsJson) {
        return buildFormEntities( null, fieldsJson);
    }

    private static List<Map<String, Object>> buildFormEntities(String parentId, List<Map<String, Object>> fieldsJson) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        if (CollectionUtil.isNotEmpty(fieldsJson)) {
            for (Object fieldObj : fieldsJson) {
                Map<String, Object> fieldJson = (Map<String, Object>) fieldObj;
                Map<String, Object> configJson = MapUtils.getMap(fieldJson, ModuleConstants.FORM_FIELD_CONFIG);
                String componentName = MapUtils.getString(configJson, "componentName");
                if (StringUtil.equalsIgnoreCase(componentName, "avue-tabs")) {
                    Map<String, Object> tabsMap = MapUtils.getMap(configJson, "childrenObj");
                    for (Object obj : tabsMap.values()) {
                        resultList.addAll(buildFormEntities( null, (List<Map<String, Object>>) obj));
                    }
                } else if (StringUtil.equalsIgnoreCase(componentName, "table")) {
                    List<Map<String, Object>> children = (List<Map<String, Object>>) configJson.get(ModuleConstants.FORM_CHILDREN);
                    String tabModuleFormId = IdWorker.get32UUID();
                    configJson.put("appFormId", tabModuleFormId);
                    configJson.put("label", MapUtils.getString(configJson, "componentTitle"));
                    configJson.put("bindTableField", MapUtils.getString(configJson, FormConstants.BIND_TABLE));
                    resultList.add(fieldJson);
                    resultList.addAll(buildFormEntities(tabModuleFormId, children));
                } else {
                    configJson.put("parentId", org.apache.commons.lang.StringUtils.defaultIfEmpty(parentId, StringPool.ZERO));
                    resultList.add(fieldJson);
                }
            }
        }
        return resultList;
    }
}
